﻿#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

#include "msp_cmn.h"
#include "qivw.h"
#include "msp_errors.h"

#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <ros/ros.h>
#include <boost/thread.hpp>
// #include <actionlib/client/simple_action_client.h>
// #include <learning_actionlib/FibonacciAction.h>
#include "sound_play/sound_play.h"
#include "audio_common_msgs/AudioData.h"
// #include "sound_play/SoundRequestAction.h"

#define IVW_AUDIO_FILE_NAME "audio/awake.pcm"
#define FRAME_LEN	640 //16k采样率的16bit音频，一帧的大小为640B, 时长20ms

// typedef actionlib::SimpleActionClient<sound_play::SoundRequestAction> Client;

sound_play::SoundClient *_sound_client_ptr;

namespace audio_awake
{
  class RosXfAwake
  {
    public:
      RosXfAwake()
      {
        // GstPad *audiopad;

        // std::string dst_type;

        // // The destination of the audio
        // ros::param::param<std::string>("~dst", dst_type, "alsasink");

        _paused = false;
        session_id = NULL;
        _msp_ret = MSP_SUCCESS;
        _err_code = MSP_SUCCESS;
        _audio_stat = MSP_AUDIO_SAMPLE_CONTINUE;
        _audio_count = 0;
	  	
	  	// client.waitForServer();
        
        session_id = QIVWSessionBegin(NULL, "ivw_threshold=0:-20,sst=wakeup", &_err_code);
        printf("\n\nsession_id = %s\n\n", session_id);
        _err_code = QIVWRegisterNotify(session_id, &RosXfAwake::onIvwMsgProc, NULL);
        if (_err_code != MSP_SUCCESS)
        	printf("\n\n_err_code = %d\n\n", _err_code);

        _sub = _nh.subscribe("audio", 10, &RosXfAwake::onAudio, this);

        // _loop = g_main_loop_new(NULL, false);

        // _pipeline = gst_pipeline_new("app_pipeline");
        // _source = gst_element_factory_make("appsrc", "app_source");
        // gst_bin_add( GST_BIN(_pipeline), _source);

        // g_signal_connect(_source, "need-data", G_CALLBACK(cb_need_data),this);

        // //_playbin = gst_element_factory_make("playbin2", "uri_play");
        // //g_object_set( G_OBJECT(_playbin), "uri", "file:///home/test/test.mp3", NULL);
        // if (dst_type == "alsasink")
        // {
        //   _decoder = gst_element_factory_make("decodebin", "decoder");
        //   g_signal_connect(_decoder, "pad-added", G_CALLBACK(cb_newpad),this);
        //   gst_bin_add( GST_BIN(_pipeline), _decoder);
        //   gst_element_link(_source, _decoder);

        //   _audio = gst_bin_new("audiobin");
        //   _convert = gst_element_factory_make("audioconvert", "convert");
        //   audiopad = gst_element_get_static_pad(_convert, "sink");
        //   _sink = gst_element_factory_make("autoaudiosink", "sink");
        //   gst_bin_add_many( GST_BIN(_audio), _convert, _sink, NULL);
        //   gst_element_link(_convert, _sink);
        //   gst_element_add_pad(_audio, gst_ghost_pad_new("sink", audiopad));
        //   gst_object_unref(audiopad);

        //   gst_bin_add(GST_BIN(_pipeline), _audio);
          
        // }
        // else
        // {
        //   _sink = gst_element_factory_make("filesink", "sink");
        //   g_object_set( G_OBJECT(_sink), "location", dst_type.c_str(), NULL);
        //   gst_bin_add(GST_BIN(_pipeline), _sink);
        //   gst_element_link(_source, _sink);
        // }

        // gst_element_set_state(GST_ELEMENT(_pipeline), GST_STATE_PLAYING);
        //gst_element_set_state(GST_ELEMENT(_playbin), GST_STATE_PLAYING);

        // _gst_thread = boost::thread( boost::bind(g_main_loop_run, _loop) );


      }

    private:

      void onAudio(const audio_common_msgs::AudioDataConstPtr &msg)
      {
        if(_paused)
        {
          // gst_element_set_state(GST_ELEMENT(_pipeline), GST_STATE_PLAYING);
          _paused = false;
        }
        // printf("\n\nmsg->data.size() = %d\n\n", msg->data.size());
        _err_code = QIVWAudioWrite(session_id, (const void *)&msg->data[0], msg->data.size(), _audio_stat);
        //printf("\n\n_err_code = %d\n\n", _err_code);
        // printf("\n\n_audio_stat = %d\n\n", _audio_stat);
        // GstBuffer *buffer = gst_buffer_new_and_alloc(msg->data.size());
        // gst_buffer_fill(buffer, 0, &msg->data[0], msg->data.size());
        // GstFlowReturn ret;

        // g_signal_emit_by_name(_source, "push-buffer", buffer, &ret);
      }

      static int onIvwMsgProc(const char *sessionID, int msg, int param1, int param2, const void *info, void *userData)
      {
      	printf("\n\nMSP_IVW_MSG_ERROR errCode = %d\n\n", msg);
		if (MSP_IVW_MSG_ERROR == msg) //唤醒出错消息
		{
			printf("\n\nMSP_IVW_MSG_ERROR errCode = %d\n\n", param1);
		}
		else if (MSP_IVW_MSG_WAKEUP == msg) //唤醒成功消息
		{
			
			_sound_client_ptr->voiceSound("hello").play();
			printf("\n\nMSP_IVW_MSG_WAKEUP result = %s\n\n", (char *)info);
		}
		else {
			printf("\n\ncb_ivw_msg_proc = %d\n\n", msg);
		}
		return 0;
      }

     // static void cb_newpad (GstElement *decodebin, GstPad *pad, 
     //                         gpointer data)
     //  {
     //    RosXfAwake *client = reinterpret_cast<RosXfAwake*>(data);

     //    GstCaps *caps;
     //    GstStructure *str;
     //    GstPad *audiopad;

     //    /* only link once */
     //    audiopad = gst_element_get_static_pad (client->_audio, "sink");
     //    if (GST_PAD_IS_LINKED (audiopad)) 
     //    {
     //      g_object_unref (audiopad);
     //      return;
     //    }

     //    /* check media type */
     //    caps = gst_pad_query_caps (pad, NULL);
     //    str = gst_caps_get_structure (caps, 0);
     //    if (!g_strrstr (gst_structure_get_name (str), "audio")) {
     //      gst_caps_unref (caps);
     //      gst_object_unref (audiopad);
     //      return;
     //    }

     //    gst_caps_unref (caps);

     //    /* link'n'play */
     //    gst_pad_link (pad, audiopad);

     //    g_object_unref (audiopad);
     //  }

     // static void cb_need_data (GstElement *appsrc,
     //               guint       unused_size,
     //               gpointer    user_data)
     // {
     //   ROS_WARN("need-data signal emitted! Pausing the pipeline");
     //   RosXfAwake *client = reinterpret_cast<RosXfAwake*>(user_data);
     //   gst_element_set_state(GST_ELEMENT(client->_pipeline), GST_STATE_PAUSED);
     //   client->_paused = true;
     // }

      ros::NodeHandle _nh;      
      ros::Subscriber _sub;
      // ros::
      boost::thread _gst_thread;

      // GstElement *_pipeline, *_source, *_sink, *_decoder, *_convert, *_audio;
      // GstElement *_playbin;
      // GMainLoop *_loop;

      bool _paused;
      int _msp_ret;
      int _err_code;
      int _audio_stat;
      long _audio_count;
      const char *session_id;

      
      // actionlib::SimpleActionClient<sound_play::SoundRequestAction> ac;
      // Client client("do_dishes", true); // true -> don't need ros::spin()
  };
}


int main (int argc, char **argv)
{
  ros::init(argc, argv, "audio_play");
  // gst_init(&argc, &argv);
  int ret = MSP_SUCCESS;
  ret = MSPLogin(NULL, NULL, "appid = 57ba78e1,engine_start = ivw,ivw_res_path =fo|res/ivw/wakeupresource.jet, work_dir = .");
  if (MSP_SUCCESS != ret)
  {
    printf("MSPLogin failed, error code: %d.\n", ret);
	//goto exit ;//登录失败，退出登录
  }
  // actionlib::SimpleActionClient<sound_play::SoundRequestGoal> ac;
  audio_awake::RosXfAwake client;
  sound_play::SoundClient _sound_client;;
  _sound_client_ptr = &_sound_client;

  ros::spin();
}


